home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / mus / play / DelfMPEG.lha / DelfMPEG / src / DelfMPEG.c < prev    next >
C/C++ Source or Header  |  2002-10-30  |  49KB  |  1,393 lines

  1. /*****************************************************************************
  2.  
  3.     DelfMPEG - MPEG audio player for Delfina DSP
  4.     Copyright (C) 1999-2002  Michael Henke
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20. *****************************************************************************/
  21.  
  22.  
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25. #include <proto/asyncio.h>
  26. #include <proto/timer.h>
  27. #include <proto/reqtools.h>
  28. #include <exec/interrupts.h>
  29. #include <exec/execbase.h>
  30. #include <exec/memory.h>
  31. #include <exec/libraries.h>
  32. #include <libraries/asyncio.h>
  33. #include <devices/timer.h>
  34. #include <libraries/reqtools.h>
  35. #include <stdlib.h>
  36. #include <math.h>
  37. #include <stdio.h>
  38.  
  39. static UBYTE version[]="$VER: DelfMPEG 0.9 (Tue 29-Oct-2002)";
  40. static UBYTE template[]=
  41.  "FILES/M,-V=VERBOSE/S,-N=NOPLAY/S,-T=SHOWTAG/S,-NL=NOFASTL/S,-NP=NOFASTP/S,"
  42.  "-F=FRAMEBUF/K/N,-A=ASYNCBUF/K/N,-FF=FFSKIP/K/N,-NT=NOTIMER/S,-M=MONO/S,"
  43.  "-S=STRICT/S,-D=DACRATE/K/N,-VOL=VOLUME/K/N,AREXX/S,-O=OUTFILE/K";
  44.  
  45. #define DEFAULT_FRAMEBUF    100
  46. #define DEFAULT_ASYNCBUF    128
  47. #define DEFAULT_FFSKIP      10
  48. #define DEFAULT_OUTFILE_ASYNCBUF 256
  49. #define DEFAULT_OUTFILE_FRAMEBUF 40
  50.  
  51. struct loadbuf {
  52.     ULONG header;
  53.     UWORD framesize, delfcopysize, crc, III_main_data_size;
  54.     UBYTE layer, mode, modext, freq, errprot, br_ind, II_jsbound, II_translate;
  55.     struct loadbuf *next;
  56.     UBYTE data[1728];   /* max: layer II, 384 kbps, 32 kHz -> 1728-4 bytes */
  57. };
  58.  
  59. struct savebuf
  60. {
  61.     struct savebuf *next;
  62.     UBYTE data[1152*2*2];
  63. };
  64.  
  65. struct loadbuf *framebuf0=NULL, *curr_load, *curr_play;
  66. LONG framebuf0size=0;
  67. struct savebuf *savebuf0=NULL, *curr_write, *curr_decoded;
  68.  
  69. static ULONG mpg_freq[4]={44100,48000,32000,0};
  70. static UBYTE *mpg_modename[4]={"stereo","j-stereo","dual-ch","single-ch"};
  71. static UBYTE *mpg_layername[3]={"I","II","III"};
  72. static UWORD mpg_bitrate[3][16]=
  73.         { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, /* I */
  74.           {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},   /* II */
  75.           {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0} }; /* III */
  76. static UWORD mpg_translate[3][2][16] =
  77.            { { { 0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0 } ,    /* 44100 stereo */
  78.                { 0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0 } } ,  /* 44100 mono   */
  79.              { { 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 } ,    /* 48000 stereo */
  80.                { 0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0 } } ,  /* 48000 mono   */
  81.              { { 0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0 } ,    /* 32000 stereo */
  82.                { 0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0 } } }; /* 32000 mono   */
  83. static UWORD mpg_sblimit[4]={27,30,8,12};
  84.  
  85. static ULONG ID3v1_TAG;
  86. UBYTE ID3v1_buffer[142];
  87.  
  88. /** static LONG pow43tab[8206]; **/
  89. #include "MP3_pow43tab.h"
  90.  
  91. static UWORD bitres_offset, bitres_ok;
  92. static UBYTE bitres_buffer[4096];
  93.  
  94. #define MPG_MD_STEREO           0
  95. #define MPG_MD_JOINT_STEREO     1
  96. #define MPG_MD_DUAL_CHANNEL     2
  97. #define MPG_MD_MONO             3
  98. #define HDR_MPEG1               0xfff80000
  99. #define HDR_CONSTANT            0x00060c00  /* layer, sampling frequency */
  100. #define ID3V1                   0x54414700  /* TAG */
  101. #define ID3V2                   0x49443300  /* ID3 */
  102. #define XING_FLAG_FRAMES        1
  103. #define XING_FLAG_BYTES         2
  104. #define XING_FLAG_TOC           4
  105.  
  106. static UBYTE *delfina_name[8]=
  107.     { "Classic","Lite","Pro","1200","Plus","UNKNOWN","UNKNOWN","UNKNOWN" };
  108.  
  109. extern struct DelfObj DSP56K_PCM;
  110. extern struct DelfObj DSP56K_MP2;
  111. extern struct DelfObj DSP56K_MP3;
  112.  
  113. #include <libraries/delfina.h>
  114. #include "PCM.h"
  115. #include "MP2.h"
  116. #include "MP3.h"
  117.  
  118. extern struct ExecBase *SysBase;
  119. struct Library *DelfinaBase=NULL;
  120. struct Library *AsyncIOBase=NULL;
  121. struct Library *TimerBase=NULL;
  122. struct ReqToolsBase *ReqToolsBase=NULL;
  123.  
  124. struct AsyncFile *file, *outfile=NULL;
  125. struct FileInfoBlock *fib=NULL;
  126. struct TagItem tag_done={TAG_DONE};
  127. UBYTE rtfilename[128]={0}, *outfilename=NULL;
  128. struct Task *mytask;
  129. ULONG bytes_total, bytes_loaded, buffers_filled, buffers_missed, write_buffers_filled;
  130. ULONG prevheader, currheader, frames_loaded, frames_played;
  131. ULONG setpos_start, setpos_framesize;
  132. ULONG decoder_busy, maindata_err;
  133. ULONG trigger_irq; /* 0=running; 1=get+put; 2=put(no get); */
  134. struct Interrupt delfint={0};
  135. struct DelfPrg *prg_pcm=NULL, *prg_mp2=NULL, *prg_mp3=NULL;
  136. struct DelfModule *mod_pcm=NULL;
  137. DELFPTR mem_il_mp2=NULL, mem_ip_mp2=NULL;
  138. DELFPTR mem_il_mp3=NULL, mem_ip_mp3=NULL;
  139. ULONG key=0;
  140.  
  141. UWORD *gb_pt, gb_buf, gb_num;
  142.  
  143. UBYTE xing_toc[100];
  144. ULONG xingvbr, xing_flags, xing_frames;
  145. ULONG channels,mono,freq,layer,pause,noplay,showtag,rexxmode;
  146. ULONG verbose, ende, havetag, nofastl, nofastp, notimer, forcemono, strict;
  147. LONG framebuf, asyncbuf, ffskip, dacrate, volume;
  148. int rc=0;
  149.  
  150. UBYTE playlist_in_use, playlist_curr_name[512], playlist_currdir;
  151. struct MinList playlist;
  152. struct playnode
  153. {
  154.     struct MinNode  minnode;
  155.     UBYTE           filename[512];
  156. };
  157.  
  158.  
  159. /**
  160. *** in arexx.c
  161. **/
  162. /* funtions */
  163. char *initRexx(void);
  164. void cleanupRexx(void);
  165. void handleRexx(void);
  166. /* variables */
  167. extern char *rexxfilename[2];
  168. extern char *portname;
  169. extern WORD rexxstatus, rexxerror;
  170. extern char rexxfiletypebuf[512];
  171. extern ULONG rexxduration, rexxposition;
  172.  
  173.  
  174.  
  175. /*
  176. **
  177. ** layer III - bit reservoir handling **
  178. **
  179. */
  180. UWORD BitReservoir(struct loadbuf *buf)
  181. {
  182.     UWORD main_data_begin, i;
  183.     UBYTE *p0, *p1;
  184.     p1= &buf->data[0];
  185.     main_data_begin= (UWORD)(*p1)<<1 | (UWORD)(*(p1+1))>>7;
  186.     /*
  187.     ** copy side information **
  188.     */
  189.     p0= &bitres_buffer[0];
  190.     for(i=32; i>0; i--) *p0++= *p1++;
  191.     /*
  192.     ** copy previous main_data **
  193.     */
  194.     p0++; /* &bitres_buffer[33] */
  195.     if(bitres_offset>=main_data_begin)
  196.     {
  197.         bitres_ok=1;
  198.         p1=p0+bitres_offset-main_data_begin;
  199.         for(i=main_data_begin; i>0; i--) *p0++= *p1++;
  200.         bitres_offset=main_data_begin;
  201.     }
  202.     else
  203.     {
  204.         bitres_ok=0;            /* not enough data in reservoir */
  205.         p0+=bitres_offset;
  206.     }
  207.     /*
  208.     ** copy current main_data **
  209.     */
  210.     i= mono ? 17 : 32;          /* side info length */
  211.     p1= &buf->data[i];          /* begin of main_data area */
  212.     i= buf->delfcopysize-i;     /* mainslots */
  213.     bitres_offset+= i;
  214.     for(; i>0; i--) *p0++= *p1++;
  215.     return(bitres_ok);
  216. }
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223. /*
  224. **
  225. ** Delfina interrupt server **
  226. **
  227. */
  228. void __saveds IntServer(void)
  229. {
  230.     if(pause)
  231.     {
  232.         /*
  233.         ** mute **
  234.         */
  235.         Delf_Run( prg_pcm->prog+PROG_PCM_MUTE, 0, DRUNF_ASYNCH, 0, 0, 0, 0 );
  236.     }
  237.     else
  238.     {
  239.         if(outfile)
  240.         {
  241.             if(trigger_irq!=2)
  242.             {
  243.                 if(write_buffers_filled < DEFAULT_OUTFILE_FRAMEBUF)
  244.                 {
  245.                     Delf_CopyMem( (APTR)(Delf_Peek(prg_pcm->ydata+DATY_PCM_BUFPTR,DMEMF_YDATA)),
  246.                                   &curr_decoded->data[0],
  247.                                   (ULONG)((forcemono?1:mono) ? 1152*2 : 1152*2*2),
  248.                                   DCPF_TO_AMY|DCPF_16BITH|((forcemono?1:mono) ? DCPF_XDATA : DCPF_LDATA) );
  249.                     curr_decoded=curr_decoded->next;
  250.                     write_buffers_filled++;
  251.                     frames_played++;
  252.                     /* set trigger, in case something goes wrong before decoding (below) */
  253.                     trigger_irq=2; /* 2=put(no get) */
  254.                 }
  255.                 else
  256.                 {
  257.                     /* no write_buffer available -> try again later */
  258.                     trigger_irq=1; /* 1=get+put */
  259.                     return;
  260.                 }
  261.             }
  262.         }
  263.         if(buffers_filled>0)
  264.         {
  265.             if(layer==2)
  266.             {
  267.                 if( !Delf_Peek( prg_mp2->ydata+DATY_MP2_BUSY,DMEMF_YDATA ) )
  268.                 {
  269.                     /* send framedata to Delfina */
  270.                     Delf_CopyMem( &curr_play->data[0],
  271.                                   (void*)(prg_mp2->xdata+DATX_MP2_INBUF),
  272.                                   (ULONG)curr_play->delfcopysize,
  273.                                   DCPF_FROM_AMY|DCPF_XDATA|DCPF_24BIT );
  274.                     Delf_Run( (outfile) ? prg_pcm->prog+PROG_PCM_DECODE : prg_mp2->prog+PROG_MP2_DECODE,
  275.                               0, DRUNF_ASYNCH,
  276.                               mono,
  277.                               Delf_Peek(prg_pcm->ydata+DATY_PCM_BUFPTR,DMEMF_YDATA),
  278.                               (ULONG)curr_play->II_translate,
  279.                               (ULONG)curr_play->II_jsbound );
  280.                     if(!outfile) frames_played++;
  281.                     buffers_filled--;
  282.                     curr_play=curr_play->next;
  283.                     trigger_irq=0; /* 0=running */
  284.                 }
  285.                 else decoder_busy++;
  286.             }
  287.             else if(layer==3)
  288.             {
  289.                 if( !Delf_Peek( prg_mp3->ydata+DATY_MP3_BUSY,DMEMF_YDATA ) )
  290.                 {
  291.                     /* send framedata to Delfina */
  292.                     if(bitres_ok)
  293.                     {
  294.                         Delf_CopyMem( &bitres_buffer[0],
  295.                                       (void*)(prg_mp3->xdata+DATX_MP3_INBUF),
  296.                                       (ULONG)curr_play->III_main_data_size+33,
  297.                                       DCPF_FROM_AMY|DCPF_XDATA|DCPF_24BIT );
  298.                         Delf_Run( (outfile) ? prg_pcm->prog+PROG_PCM_DECODE : prg_mp3->prog+PROG_MP3_DECODE,
  299.                                   0, DRUNF_ASYNCH,
  300.                                   mono,
  301.                                   Delf_Peek(prg_pcm->ydata+DATY_PCM_BUFPTR,DMEMF_YDATA),
  302.                                   (ULONG)curr_play->modext,
  303.                                   0 );
  304.                     }
  305.                     else maindata_err++;
  306.                     if(!outfile) frames_played++;
  307.                     buffers_filled--;
  308.                     curr_play=curr_play->next;
  309.                     if(buffers_filled>0) BitReservoir(curr_play);
  310.                     trigger_irq=0; /* 0=running */
  311.                 }
  312.                 else decoder_busy++;
  313.             }
  314.         }
  315.         else
  316.         {
  317.             if(frames_loaded>1) buffers_missed++;
  318.         }
  319.     }
  320. }
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328. void initPCM(void)
  329. {
  330.     if(!prg_pcm) return;
  331.     Delf_Run(prg_pcm->prog+PROG_PCM_INIT, 0, 0,
  332.             (ULONG)(forcemono?1:mono),
  333.             (volume>100) ? (volume*0x7fffff)/200 : (volume*0x400000)/100,
  334.             freq, 0 );
  335. }
  336.  
  337.  
  338. /*
  339. **
  340. ** allocate Delfina resources **
  341. **
  342. */
  343. int InitDelfina(void)
  344. {
  345.     ULONG decoder_address;
  346.     if(noplay) return(0);
  347.     if(!(prg_pcm=Delf_AddPrg(&DSP56K_PCM)))
  348.     {
  349.         printf("**not enough Delfina memory\n");
  350.         return(0);
  351.     }
  352.     switch(layer)
  353.     {
  354.         case 2:
  355.             if(!nofastl)
  356.                 mem_il_mp2=Delf_AllocMem(INTL_MP2_DATL, DMEMF_LDATA|DMEMF_INTERNAL|DMEMF_ALIGN_64);
  357.             if(!nofastp)
  358.                 mem_ip_mp2=Delf_AllocMem(INTP_MP2_PROG, DMEMF_PROG|DMEMF_INTERNAL);
  359.             if(!(prg_mp2=Delf_AddPrg(&DSP56K_MP2)))
  360.             {
  361.                 printf("**not enough Delfina memory\n");
  362.                 return(0);
  363.             }
  364.             Delf_Run(prg_mp2->prog+PROG_MP2_INIT, 0, 0,
  365.                      mem_il_mp2, mem_ip_mp2, 0, 0);
  366.             if((!mem_il_mp2 && !nofastl) || (!mem_ip_mp2 && !nofastp))
  367.             {
  368.                 printf("**warning: not enough internal DSP memory\n"
  369.                        "  (the decoder might run too slowly and produce \"jerky\" sound)\n");
  370.             }
  371.             Delf_Poke(prg_mp2->ydata+DATY_MP2_FORCEMONO, DMEMF_YDATA, forcemono);
  372.             decoder_address = (ULONG)(prg_mp2->prog+PROG_MP2_DECODE);
  373.             break;
  374.         case 3:
  375.             if(!nofastl)
  376.                 mem_il_mp3=Delf_AllocMem(INTL_MP3_DATL, DMEMF_LDATA|DMEMF_INTERNAL|DMEMF_ALIGN_64);
  377.             if(!nofastp)
  378.                 mem_ip_mp3=Delf_AllocMem(INTP_MP3_PROG, DMEMF_PROG|DMEMF_INTERNAL);
  379.             if(!(prg_mp3=Delf_AddPrg(&DSP56K_MP3)))
  380.             {
  381.                 printf("**not enough Delfina memory\n");
  382.                 return(0);
  383.             }
  384.             Delf_CopyMem(pow43tab, (void*)(prg_mp3->ydata+DATY_MP3_POW43TAB),
  385.                          8206*4, DCPF_FROM_AMY|DCPF_YDATA|DCPF_32BIT);
  386.             Delf_Run(prg_mp3->prog+PROG_MP3_INIT, 0, 0,
  387.                      mem_il_mp3, mem_ip_mp3,
  388.                      (ULONG)curr_play->freq,
  389.                      (ULONG)0);
  390.             if((!mem_il_mp3 && !nofastl) || (!mem_ip_mp3 && !nofastp))
  391.             {
  392.                 printf("**warning: not enough internal DSP memory\n"
  393.                        "  (the decoder might run too slowly and produce \"jerky\" sound)\n");
  394.             }
  395.             Delf_Poke(prg_mp3->ydata+DATY_MP3_FORCEMONO, DMEMF_YDATA, forcemono);
  396.             decoder_address = (ULONG)(prg_mp3->prog+PROG_MP3_DECODE);
  397.             break;
  398.         default:
  399.             printf("**layer %d is not supported\n",layer);
  400.             return(0);
  401.     }
  402.     /*initPCM();*/
  403.     Delf_Run(prg_pcm->prog+PROG_PCM_INIT, 0, 0,
  404.             (ULONG)(forcemono?1:mono),
  405.             (volume>100) ? (volume*0x7fffff)/200 : (volume*0x400000)/100,
  406.             freq,
  407.             decoder_address );
  408.     delfint.is_Code=(void(*)(void))IntServer;
  409.     if (!(key=Delf_AddIntServer(prg_pcm->prog+PROG_PCM_INTKEY,&delfint)))
  410.     {
  411.         printf("**couldn't create interrupt server\n");
  412.         return(0);
  413.     }
  414.     if(!outfile)
  415.     {
  416.         if(!(mod_pcm=Delf_AddModule(DM_Inputs, 0,
  417.                                     DM_Outputs, 1,
  418.                                     DM_Code, prg_pcm->prog+PROG_PCM_MODULE,
  419.                                     DM_Freq, dacrate?dacrate*1000:freq,
  420.                                     DM_Name, "DelfMPEG", 0)))
  421.         {
  422.             printf("**couldn't create DelfModule\n");
  423.             return(0);
  424.         }
  425.     }
  426.     return(1);
  427. }
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435. /*
  436. **
  437. ** free Delfina resources **
  438. **
  439. */
  440. void CleanupDelfina(void)
  441. {
  442.     Delay(10);
  443.     if(mod_pcm) {Delf_RemModule(mod_pcm); mod_pcm=NULL;}
  444.     if(key)     {Delf_RemIntServer(key); key=0;}
  445.     if(prg_mp2) {Delf_RemPrg(prg_mp2); prg_mp2=NULL;}
  446.     if(prg_mp3) {Delf_RemPrg(prg_mp3); prg_mp3=NULL;}
  447.     if(prg_pcm) {Delf_RemPrg(prg_pcm); prg_pcm=NULL;}
  448.     if(mem_il_mp2) {Delf_FreeMem(mem_il_mp2,DMEMF_LDATA|DMEMF_INTERNAL); mem_il_mp2=NULL;}
  449.     if(mem_ip_mp2) {Delf_FreeMem(mem_ip_mp2,DMEMF_PROG |DMEMF_INTERNAL); mem_ip_mp2=NULL;}
  450.     if(mem_il_mp3) {Delf_FreeMem(mem_il_mp3,DMEMF_LDATA|DMEMF_INTERNAL); mem_il_mp3=NULL;}
  451.     if(mem_ip_mp3) {Delf_FreeMem(mem_ip_mp3,DMEMF_PROG |DMEMF_INTERNAL); mem_ip_mp3=NULL;}
  452. }
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459. UWORD GetBits(UWORD num)
  460. {
  461.     UWORD val=0;
  462.     for(; num>0; num--)
  463.     {
  464.         if(gb_num==0)
  465.         {
  466.             gb_buf= *gb_pt++;
  467.             gb_num= 16;
  468.         }
  469.         gb_num--;
  470.         val+= val;
  471.         val|= (gb_buf>>gb_num)&1;
  472.     }
  473.     return(val);
  474. }
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481. UWORD CheckHeader(struct loadbuf *lb)
  482. {
  483.     UWORD result=0;
  484.  
  485.     /** let's ignore these header infos (we don't need them here)
  486.     *** ->version, ->extension, ->copyright, ->original, ->emphasis **/
  487.     lb->header  = currheader;
  488.     lb->layer   = 4-((currheader>>17)&0x3);
  489.     lb->mode    = ((currheader>>6)&0x3);
  490.     lb->modext  = ((currheader>>4)&0x3);
  491.     lb->br_ind  = ((currheader>>12)&0xf);
  492.     lb->freq    = ((currheader>>10)&0x3);
  493.     lb->errprot = ((currheader>>16)&0x1)^0x1;
  494.  
  495.     if( (lb->layer==4)  ||
  496.         (lb->br_ind==0) ||
  497.         (lb->br_ind==15)||
  498.         (lb->freq==3)   )   result+=1;
  499.     if(prevheader)
  500.         if( (currheader&HDR_CONSTANT)!=(prevheader&HDR_CONSTANT) ||
  501.             ((lb->mode==MPG_MD_MONO?1:2)!=channels) ) result+=2;
  502.     if((currheader&HDR_MPEG1)!=HDR_MPEG1) result+=4;
  503.     return(result);
  504. }
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511. /*
  512. **
  513. ** analyze frame header and load frame **
  514. **
  515. */
  516. int ReadFrame(struct loadbuf *lb)
  517. {
  518.     LONG s0,s1,i0,i1;
  519.     UWORD md;
  520.  
  521.     if((md=CheckHeader(lb)))
  522.     {
  523.         if(!prevheader && strict) return(0);    /*error*/
  524.  
  525.         if((currheader&0xffffff00)==ID3V1)
  526.         {
  527.             if(verbose) printf(" (ID3v1 tag)\n");
  528.         }
  529.         else if(prevheader)
  530.         {
  531.             if(md&4)      printf(" (lost frame sync - non-audio data)\n");
  532.             else if(md&1) printf(" (invalid frame header)\n");
  533.             else if(md&2) printf(" (unsupported frame header change)\n");
  534.             if(verbose)
  535.                 printf("**position=0x%08lx  currheader=0x%08lx  "
  536.                    "prevheader=0x%08lx\n",bytes_loaded,currheader,prevheader);
  537.         }
  538.  
  539.         if(!strict)
  540.         {
  541.             s0=0;
  542.             while((s0<32*1024) && md)
  543.             {
  544.                 bytes_loaded++; s0++;
  545.                 currheader<<=8;
  546.                 i0=ReadCharAsync(file);
  547.                 if(i0<0) break;
  548.                 else
  549.                 {
  550.                     currheader|=i0;
  551.                     md=CheckHeader(lb);
  552.                 }
  553.             }
  554.             if(verbose) printf("**skipped %d bytes - resync %s.\n",s0,md?"failed":"ok");
  555.         }
  556.  
  557.         if(md) return(0);   /*error: resync failed */
  558.     }
  559.  
  560.  
  561.     if(channels==0) channels=(lb->mode==MPG_MD_MONO)?1:2;
  562.     lb->II_translate= mpg_translate [lb->freq]
  563.                                     [(lb->mode==MPG_MD_MONO)?1:0]
  564.                                     [lb->br_ind];
  565.     lb->II_jsbound= (lb->mode==MPG_MD_JOINT_STEREO) ?
  566.                             (lb->modext<<2)+4 : mpg_sblimit[lb->II_translate];
  567.  
  568.     lb->framesize = (mpg_bitrate[lb->layer-1][lb->br_ind]*144000)
  569.                     /mpg_freq[lb->freq] + ((currheader>>9)&0x1); /* padding */
  570.     lb->delfcopysize = lb->framesize-4;
  571.  
  572.     s0=i0=2;
  573.     if(lb->errprot)
  574.     {
  575.         i0=ReadAsync(file,&lb->crc,s0);
  576.         lb->delfcopysize-=s0;
  577.     }
  578.     s1=i1=lb->delfcopysize;
  579.  
  580.     /** do not read layer I frame because it might be too large !! **/
  581.     if(lb->layer>1) i1=ReadAsync(file,&lb->data[0],s1);
  582.  
  583.  
  584.     /*** at beginning of file: try to recognize the second frame, too ***/
  585.     if(!prevheader)
  586.     {
  587.         /** seek over first layer I frame (it has not been read) **/
  588.         if(lb->layer==1) i1=SeekAsync(file,s1,MODE_CURRENT);
  589.         if(PeekAsync(file,&currheader,4)==4)
  590.         {
  591.             ULONG ch=currheader;
  592.             prevheader=currheader;
  593.             if(CheckHeader(lb->next)) return(0); /*error*/
  594.             prevheader=0;
  595.             currheader=ch;
  596.         }
  597.     }
  598.  
  599.  
  600.     if(!((i0==s0) && (i1==s1)))
  601.     {
  602.         if((i0==-1) || (i1==-1))
  603.             printf(" (file read error)\n");
  604.         else
  605.             if(verbose) printf(" (unexpected EOF - got %d of %d bytes)\n",i1,s1);
  606.         return(0);  /*error*/
  607.     }
  608.  
  609.     if(lb->layer==3)
  610.     {
  611.         gb_pt= (UWORD*)&lb->data[2]; gb_num=0;
  612.         if(lb->mode==MPG_MD_MONO)
  613.         {
  614.             GetBits(9+5+4-16);
  615.             md=GetBits(12);
  616.         }
  617.         else
  618.         {
  619.             GetBits(9+3+8-16);
  620.             md=GetBits(12);
  621.             GetBits(59-12);
  622.             md+=GetBits(12);
  623.             GetBits(59-12);
  624.             md+=GetBits(12);
  625.         }
  626.         GetBits(59-12);
  627.         md+=GetBits(12);
  628.         lb->III_main_data_size=(md+7)>>3;
  629.  
  630.         if(lb->mode!=MPG_MD_JOINT_STEREO) lb->modext=0;
  631.  
  632.         if(buffers_filled==0) BitReservoir(lb);
  633.     }
  634.  
  635.     buffers_filled++;
  636.     frames_loaded++;
  637.     bytes_loaded+=lb->framesize;
  638.  
  639.     return(1);  /*ok*/
  640. }
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647. void setPosition(ULONG seconds)     /*** WARNING: quick & dirty hack !! ***/
  648. {
  649.     int loop,maxl;
  650.     if(strict) return;
  651.  
  652.     pause++;
  653.     if(seconds>rexxduration) seconds=rexxduration;
  654.   /*printf("----setPosition %d\n",seconds);*/
  655.  
  656.     if(xing_flags&XING_FLAG_TOC)
  657.     {
  658.         /*interpolate in TOC to get file seek point in bytes*/
  659.         int a;
  660.         float fa, fb, fx;
  661.         fx=100.0*(float)seconds/(float)rexxduration;
  662.         a=(int)fx;  if(a>99) a=99;
  663.         fa=xing_toc[a];  
  664.         if(a<99) fb=xing_toc[a+1]; else fb=256.0;
  665.         fx=(fa+(fb-fa)*(fx-a))/256.0;
  666.         bytes_loaded=(int)(fx*bytes_total); 
  667.         frames_loaded=frames_played=seconds*freq/1152;
  668.       /*printf("----Xing VBR new pos: %ld of %ld bytes\n",bytes_loaded,bytes_total);*/
  669.     }
  670.     else
  671.     {
  672.         bytes_loaded=setpos_start+(seconds*(bytes_total-setpos_start))/rexxduration;
  673.         frames_loaded=frames_played=bytes_loaded/setpos_framesize;
  674.       /*printf("----plain new pos: %ld of %ld bytes\n",bytes_loaded,bytes_total);*/
  675.     }
  676.  
  677.     curr_load=curr_play=framebuf0;
  678.     buffers_filled=0;
  679.     bitres_offset=0;
  680.  
  681.     SeekAsync(file,bytes_loaded,MODE_START);
  682.     maxl=((framebuf>8) ? 8 : framebuf);
  683.     for(loop=0; loop<maxl; loop++)
  684.     {
  685.         ReadAsync(file,&currheader,4);
  686.         if(ReadFrame(curr_load))
  687.         {
  688.             prevheader=currheader;
  689.             curr_load=curr_load->next;
  690.         }
  691.         else {bytes_loaded=bytes_total; break;}
  692.     }
  693.     pause--;
  694. }
  695.  
  696.  
  697.  
  698.  
  699.  
  700.     
  701.  
  702.  
  703. int main(void)
  704. {
  705.     struct RDArgs *rdargs;
  706.     LONG args[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, r1, i, taskpri;
  707.     UBYTE **files_pt, *filename;
  708.     double duration, duration2;
  709.     ULONG sigs, minutes, seconds, millisec, curr_print_pos, prev_print_pos;
  710.     struct timeval time1,time2;
  711.     struct rtFileRequester *rtfilereq=NULL;
  712.     struct rtFileList *rtfilelist=NULL, *rtfilelist_curr=NULL;
  713.     BPTR lock_newdir=NULL, lock_olddir=NULL;
  714.  
  715.     /*
  716.     **
  717.     ** read args **
  718.     **
  719.     */
  720.     rdargs=ReadArgs(template,args,NULL);
  721.     printf("\33[1m%s by Smack/Infect!\33[0m\n",&version[6]);
  722.     files_pt=(char**)args[0];
  723.     verbose=args[1];
  724.     noplay=args[2];
  725.     showtag=args[3];
  726.     nofastl=args[4];
  727.     nofastp=args[5];
  728.     if(args[6]) framebuf=(*(LONG*)args[6]); else framebuf=DEFAULT_FRAMEBUF;
  729.     if(args[7]) asyncbuf=(*(LONG*)args[7]); else asyncbuf=DEFAULT_ASYNCBUF;
  730.     if(args[8]) ffskip=(*(LONG*)args[8]); else ffskip=DEFAULT_FFSKIP;
  731.     notimer=args[9];
  732.     forcemono=args[10];
  733.     strict=args[11];
  734.     if(args[12]) dacrate=(*(LONG*)args[12]); else dacrate=0;
  735.     if(args[13]) volume=(*(LONG*)args[13]); else volume=100;
  736.     rexxmode=args[14];
  737.     outfilename=(UBYTE*)args[15];
  738.  
  739.     if(verbose)
  740.         printf(
  741.         "\n"
  742.         "  DelfMPEG - MPEG audio player for Delfina DSP\n"
  743.         "  Copyright (C) 1999-2002  Michael Henke\n"
  744.         "\n"
  745.         "  This program is free software; you can redistribute it and/or modify\n"
  746.         "  it under the terms of the GNU General Public License as published by\n"
  747.         "  the Free Software Foundation; either version 2 of the License, or\n"
  748.         "  (at your option) any later version.\n"
  749.         "\n"
  750.         "  This program is distributed in the hope that it will be useful,\n"
  751.         "  but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  752.         "  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  753.         "  GNU General Public License for more details.\n"
  754.         "\n"
  755.         "  You should have received a copy of the GNU General Public License\n"
  756.         "  along with this program; if not, write to the Free Software\n"
  757.         "  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
  758.         "\n"  );
  759.  
  760.  
  761.     /*
  762.     **
  763.     ** open libraries & stuff **
  764.     **
  765.     */
  766.     playlist_in_use=0;
  767.     NewList((struct List*)&playlist);
  768.     if(!noplay)
  769.     {
  770.         ULONG delfina_model;
  771.         double delfina_dspclock;
  772.         if (!(DelfinaBase=OpenLibrary("delfina.library",4)))
  773.         {
  774.             printf("**unable to open delfina.library V4\n");
  775.             rc=20;
  776.             goto exit_clean;
  777.         }
  778.         delfina_model=Delf_GetAttr(DA_HWInfo,0);
  779.         delfina_model&=0xff; i=0;
  780.         while(delfina_model) { delfina_model>>=1; i++; }
  781.         delfina_model=i ? (i-1) : 7;
  782.         delfina_dspclock=(double)Delf_GetAttr(DA_DSPClock,0)/1000000.0;
  783.         if(verbose)
  784.             printf("\n  Delfina %s: delfina.library v%d.%d, %d K memory, %.1f MHz DSP\n",
  785.                    delfina_name[delfina_model],
  786.                    DelfinaBase->lib_Version,
  787.                    DelfinaBase->lib_Revision,
  788.                    (Delf_AvailMem(DMEMF_PROG|DMEMF_TOTAL)+Delf_AvailMem(DMEMF_YDATA|DMEMF_TOTAL)+1023)>>10,
  789.                    delfina_dspclock );
  790.     }
  791.     if (!(AsyncIOBase=OpenLibrary("asyncio.library",39))) {
  792.         printf("**unable to open asyncio.library V39\n");
  793.         rc=20;
  794.         goto exit_clean;
  795.     }
  796.     TimerBase=(struct Library*)FindName(&SysBase->DeviceList,"timer.device");
  797.     mytask=FindTask(NULL);
  798.     if(!(fib=AllocDosObject(DOS_FIB,&tag_done)))
  799.     {
  800.         rc=20;
  801.         goto exit_clean;
  802.     }
  803.     if(rexxmode)
  804.     {
  805.         char *res;
  806.         if((res=initRexx()))
  807.         {
  808.             printf("**initRexx failed (%s)\n",res);
  809.             rc=20;
  810.             goto exit_clean;
  811.         }
  812.     }
  813.         
  814.  
  815.     /*
  816.     **
  817.     ** init load buffers **
  818.     **
  819.     */
  820.     if(framebuf<4) framebuf=4;
  821.     if(asyncbuf<4) asyncbuf=4;
  822.     if(ffskip<1) ffskip=1;
  823.     if(dacrate<0) dacrate=0;
  824.     if(dacrate>48) dacrate=48;
  825.     if(dacrate) dacrate=Delf_GetAttr(DA_Freq,dacrate*1000)/1000;
  826.     if(volume<0) volume=0;
  827.     if(volume>200) volume=200;
  828.     framebuf0size=framebuf*(LONG)sizeof(struct loadbuf);
  829.     if(verbose)
  830.         printf( "\n   reader: framebuf=%d (%d K), asyncbuf=%d K, ffskip=%d, strict=o%s\n"
  831.                 "  decoder: forcemono=o%s, dacrate=%d kHz, volume=%d%%\n",
  832.                 framebuf, (framebuf0size+1023)>>10, asyncbuf, ffskip, strict?"n":"ff",
  833.                 forcemono?"n":"ff", dacrate, volume );
  834.     if(!(framebuf0=(struct loadbuf*)AllocMem(framebuf0size,MEMF_PUBLIC)))
  835.     {
  836.         printf("**not enough memory for \"framebuf\"\n");
  837.         rc=20;
  838.         goto exit_clean;
  839.     }
  840.     for(i=0;i<framebuf-1;i++) framebuf0[i].next= &framebuf0[i+1];
  841.     framebuf0[framebuf-1].next=framebuf0;
  842.  
  843.     if((outfilename!=NULL) && (outfilename[0]!=0)) /* non-empty string */
  844.     {
  845.         if(!(outfile=OpenAsync(outfilename,MODE_WRITE,DEFAULT_OUTFILE_ASYNCBUF*1024)))
  846.         {
  847.             printf("**unable to open output file: %s\n",outfilename);
  848.             rc=20;
  849.             goto exit_clean;
  850.         }
  851.         if(!(savebuf0=(struct savebuf*)AllocMem(DEFAULT_OUTFILE_FRAMEBUF*(LONG)sizeof(struct savebuf),MEMF_PUBLIC)))
  852.         {
  853.             printf("**not enough memory for \"savebuf\"\n");
  854.             rc=20;
  855.             goto exit_clean;
  856.         }
  857.         for(i=0;i<DEFAULT_OUTFILE_FRAMEBUF-1;i++) savebuf0[i].next= &savebuf0[i+1];
  858.         savebuf0[DEFAULT_OUTFILE_FRAMEBUF-1].next=savebuf0;
  859.     }
  860.  
  861.  
  862.     /*
  863.     **
  864.     ** reqtools filerequester if no files specified **
  865.     **
  866.     */
  867.     if(!files_pt && !rexxmode)
  868.     {
  869.         if((ReqToolsBase=(struct ReqToolsBase*)OpenLibrary("reqtools.library",38)))
  870.         {
  871.             if(!(rtfilereq=rtAllocRequest(RT_FILEREQ,NULL)))
  872.             {
  873.                 rc=10;
  874.                 goto exit_clean;
  875.             }
  876.         }
  877.         else
  878.         {
  879.             rc=5;
  880.             goto exit_clean;
  881.         }
  882.     }
  883.  
  884.     rexxduration=rexxposition=0;
  885.     pause=1; rexxerror=0;   /* initialize */
  886.  
  887. next_filereq:
  888.     if(rtfilereq)
  889.     {
  890.         rtfilelist=rtFileRequest( rtfilereq, &rtfilename[0],
  891.                                   "DelfMPEG: select MPEG audio files",
  892.                                   RTFI_Flags, FREQF_MULTISELECT|FREQF_PATGAD,
  893.                                   TAG_DONE );
  894.         if(rtfilelist)
  895.         {
  896.             rtfilelist_curr=rtfilelist;
  897.             if(rtfilereq->Dir)
  898.             {
  899.                 lock_newdir=Lock(rtfilereq->Dir,SHARED_LOCK);
  900.                 lock_olddir=CurrentDir(lock_newdir);
  901.             }
  902.         }
  903.         else goto exit_clean;
  904.     }
  905.  
  906. next_rexxloop:
  907.     if(rexxmode)
  908.     {
  909.         ende=1; rexxstatus=0;   /* status: stop */
  910.         rexxfilename[0]=NULL;
  911.         printf("\n  ARexx mode: waiting for 'PLAY <file>' on port '%s'\n",portname);
  912.         while(!rexxfilename[0])
  913.         {
  914.             handleRexx();
  915.             if(CheckSignal(SIGBREAKF_CTRL_D)) goto exit_clean;
  916.             if(ende>1) goto exit_clean;     /* QUIT command */
  917.             Delay(1);
  918.         }
  919.         files_pt=rexxfilename;
  920.         rexxduration=rexxposition=0;
  921.         rexxfiletypebuf[0]=0;
  922.         rexxerror=0;                /* PLAY command clears rexxerror */
  923.         rexxstatus=1;               /* status: play */
  924.         if(pause>1) rexxstatus=2;   /* status: pause */
  925.     }
  926.     ende=0;
  927.  
  928.     /*
  929.     **
  930.     ** files loop **
  931.     **
  932.     */
  933.     do
  934.     {
  935.         /*
  936.         **
  937.         ** get next filename **
  938.         **
  939.         */
  940. next_file:
  941.         if(playlist_in_use)
  942.         {
  943.             struct playnode *node = (struct playnode*) RemHead((struct List*)&playlist);
  944.             if(node)
  945.             {
  946.                 CopyMem(node->filename,playlist_curr_name,sizeof(playlist_curr_name));
  947.                 filename=playlist_curr_name;
  948.                 FreeMem(node,sizeof(struct playnode));
  949.             }
  950.             else
  951.             {
  952.                 if(playlist_currdir)
  953.                 {
  954.                     if(lock_olddir) { CurrentDir(lock_olddir); lock_olddir=NULL; }
  955.                     if(lock_newdir) { UnLock(lock_newdir); lock_newdir=NULL; }
  956.                     playlist_currdir=0;
  957.                 }
  958.                 playlist_in_use=0;
  959.                 goto next_file;
  960.             }
  961.         }
  962.         else if(rtfilelist)
  963.         {
  964.             if(rtfilelist_curr)
  965.             {
  966.                 filename=rtfilelist_curr->Name;
  967.                 rtfilelist_curr=rtfilelist_curr->Next;
  968.             }
  969.             else filename=NULL;
  970.         }
  971.         else filename=(*files_pt++);
  972.  
  973.         if(!filename) break;
  974.         printf("\n  file: %s\n",filename);
  975.  
  976.         havetag = 0;
  977.         setpos_start = prev_print_pos = curr_print_pos = 0;
  978.         curr_load = curr_play = framebuf0;
  979.         curr_write = curr_decoded = savebuf0;
  980.         trigger_irq = 2;
  981.         bytes_loaded = buffers_filled = buffers_missed = write_buffers_filled = 0;
  982.         prevheader = currheader = channels = 0;
  983.         frames_loaded = frames_played = 0;
  984.         decoder_busy = maindata_err = 0;
  985.         bitres_offset = 0;
  986.  
  987.         /*
  988.         **
  989.         ** open file **
  990.         **
  991.         */
  992.         rexxerror=20;  /* file not found */
  993.         if((file=OpenAsync(filename,MODE_READ,asyncbuf<<10)))
  994.         {
  995.             /*
  996.             **
  997.             ** read first frame + output some info **
  998.             **
  999.             */
  1000.             ExamineFH(file->af_File,fib);
  1001.             bytes_total=fib->fib_Size;
  1002.             ReadAsync(file,&currheader,4);
  1003.  
  1004.             if(currheader==0x52494646)          /* RIFF WAVE header */
  1005.             {
  1006.                 UBYTE b[8];
  1007.                 ReadAsync(file,&b[0],8);
  1008.                 r1=20;  /* 12+8 bytes */
  1009.                 while(1)
  1010.                 {
  1011.                     if(ReadAsync(file,&b[0],8)!=8)   /* chunk name + length */
  1012.                         break;  /* EOF -> ReadFrame() detects this */
  1013.                     r1=((LONG)b[7]<<24)|((LONG)b[6]<<16)|((LONG)b[5]<<8)|(LONG)b[4];
  1014.                     if((b[0]=='d')&&(b[1]=='a')&&(b[2]=='t')&&(b[3]=='a'))
  1015.                         break;                       /* found data chunk */
  1016.                     SeekAsync(file,r1,MODE_CURRENT); /* skip unknown chunk */
  1017.                 }
  1018.                 bytes_total=r1;
  1019.                 if(verbose)
  1020.                     printf("  found RIFF header (data chunk: %ld bytes)\n",r1);
  1021.                 ReadAsync(file,&currheader,4);
  1022.             }
  1023.  
  1024.             if((currheader&0xFFFFFF00)==ID3V2)  /* found ID3V2 tag */
  1025.             {
  1026.                 UBYTE b[6];
  1027.                 ReadAsync(file,&b[0],6);
  1028.                 r1=(LONG)b[5]|((LONG)b[4]<<7)|((LONG)b[3]<<14)|((LONG)b[2]<<21);
  1029.                 SeekAsync(file,r1,MODE_CURRENT);
  1030.                 r1+=10;
  1031.                 if(verbose)
  1032.                     printf("  skipped ID3v2.%d.%d tag (%d bytes)\n",
  1033.                             currheader&0xFF, b[0], r1);
  1034.                 bytes_loaded+=r1;
  1035.                 ReadAsync(file,&currheader,4);
  1036.             }
  1037.  
  1038.             rexxerror=30;  /* file not recognized as MPEG-1 audio */
  1039.             if(!ReadFrame(curr_load))   /* recognize the MPEG audio file */
  1040.             {
  1041.                 printf("**not recognized as MPEG-1 audio\n");
  1042.                 /*
  1043.                 ** try to read the file as playlist **************************
  1044.                 */
  1045.                 if(!playlist_in_use)
  1046.                 {
  1047.                     struct playnode *node=NULL;
  1048.                     int lines_read=0, lines_ok=0, len, i;
  1049.                     BPTR fh;
  1050.                     SeekAsync(file,0,MODE_START);
  1051.                     if(verbose) printf("  interpreting file as playlist.  valid entries:\n");
  1052.                     if(!lock_newdir)
  1053.                     {
  1054.                         i=PathPart(filename)-filename;
  1055.                         if(i>0)
  1056.                         {
  1057.                             UBYTE temp=filename[i];
  1058.                             filename[i]=0;
  1059.                             lock_newdir=Lock(filename,SHARED_LOCK);
  1060.                             lock_olddir=CurrentDir(lock_newdir);
  1061.                             if(verbose) printf("  playlist current dir: %s\n",filename);
  1062.                             filename[i]=temp;
  1063.                             playlist_currdir=1;
  1064.                         }
  1065.                     }
  1066.                     for(;;)
  1067.                     {
  1068.                         if(!node) node=AllocMem(sizeof(struct playnode),MEMF_PUBLIC|MEMF_CLEAR);
  1069.                         if(!node) break;    /* mem error */
  1070.                         len=ReadLineAsync(file,node->filename,sizeof(node->filename));
  1071.                         if(len<=0) break;   /* EOF or read error */
  1072.                         if(node->filename[0]!='#')
  1073.                         {
  1074.                             lines_read++;
  1075.                             for(i=0;i<len;i++) if(node->filename[i]<' ') node->filename[i]=0;
  1076.                             fh=Open(node->filename,MODE_OLDFILE);
  1077.                             if(fh)
  1078.                             {
  1079.                                 Close(fh); lines_ok++;
  1080.                                 if(verbose) printf("    %s\n",node->filename);
  1081.                                 AddTail((struct List*)&playlist,(struct Node*)node);
  1082.                                 node=NULL;
  1083.                                 playlist_in_use=1;
  1084.                             }
  1085.                         }
  1086.                         if((lines_read>=32) && (lines_ok==0)) break; /* error: no valid lines */
  1087.                     }
  1088.                     if((lines_ok>0) || verbose) printf("  playlist:  %d valid entries  (%d entries were read)\n",lines_ok,lines_read);
  1089.                     if(lines_ok==0)
  1090.                     {
  1091.                         printf("**not usable as playlist\n");
  1092.                         if(playlist_currdir)
  1093.                         {
  1094.                             if(lock_olddir) { CurrentDir(lock_olddir); lock_olddir=NULL; }
  1095.                             if(lock_newdir) { UnLock(lock_newdir); lock_newdir=NULL; }
  1096.                             playlist_currdir=0;
  1097.                         }
  1098.                     }
  1099.                     if(node) FreeMem(node,sizeof(struct playnode));
  1100.                 }
  1101.                 CloseAsync(file);
  1102.                 goto next_file;
  1103.             }
  1104.             else    /* ReadFrame ok */
  1105.             {
  1106.                 if(showtag)
  1107.                 {
  1108.                     LONG oldpos;
  1109.                     oldpos=SeekAsync(file, -128, MODE_END);
  1110.                     ID3v1_TAG=0; havetag=0;
  1111.                     ReadAsync(file, &ID3v1_TAG, 3);
  1112.                     if((ID3v1_TAG&0xffffff00)==ID3V1)
  1113.                     {
  1114.                         ReadAsync(file,&ID3v1_buffer[00],30); /* title  */
  1115.                         ReadAsync(file,&ID3v1_buffer[31],30); /* artist */
  1116.                         ReadAsync(file,&ID3v1_buffer[62],30); /* album  */
  1117.                         ReadAsync(file,&ID3v1_buffer[93],04); /* year   */
  1118.                         ReadAsync(file,&ID3v1_buffer[98],30); /* comment*/
  1119.                         ReadAsync(file,&ID3v1_buffer[141],1); /* genre  */
  1120.                         for(i=0;i<140;i++)
  1121.                         {
  1122.                             if(ID3v1_buffer[i]<0x20) ID3v1_buffer[i]=0x20;
  1123.                         }
  1124.                         ID3v1_buffer[30]=0x00;
  1125.                         ID3v1_buffer[30+1+30]=0x00;
  1126.                         ID3v1_buffer[30+1+30+1+30]=0x00;
  1127.                         ID3v1_buffer[30+1+30+1+30+1+4]=0x00;
  1128.                         ID3v1_buffer[30+1+30+1+30+1+4+1+30]=0x00;
  1129.                         havetag=1;
  1130.                     }
  1131.                     SeekAsync(file, oldpos, MODE_START);
  1132.                 }
  1133.  
  1134.                 {   /* look for Xing VBR header */
  1135.                     UBYTE *xpt;
  1136.                     xingvbr=xing_flags=0;
  1137.                     xpt= &curr_load->data[0];
  1138.                     xpt+=(curr_load->mode==MPG_MD_MONO) ? 17 : 32;
  1139.                     if((xpt[0]=='X') &&
  1140.                        (xpt[1]=='i') &&
  1141.                        (xpt[2]=='n') &&
  1142.                        (xpt[3]=='g') )
  1143.                     {
  1144.                         xingvbr++;
  1145.                         xpt+=4;
  1146.                         xing_flags= (ULONG)xpt[0]<<24 | (ULONG)xpt[1]<<16 |
  1147.                                     (ULONG)xpt[2]<<8  | (ULONG)xpt[3];
  1148.                         xpt+=4;
  1149.                         if(xing_flags&XING_FLAG_FRAMES)
  1150.                         {
  1151.                             xing_frames=(ULONG)xpt[0]<<24 | (ULONG)xpt[1]<<16 |
  1152.                                         (ULONG)xpt[2]<<8  | (ULONG)xpt[3];
  1153.                             xpt+=4;
  1154.                         }
  1155.                         else xing_frames=0;
  1156.                         if(xing_flags&XING_FLAG_BYTES) xpt+=4;
  1157.                         if(xing_flags&XING_FLAG_TOC)
  1158.                         {
  1159.                             for(i=0;i<100;i++) xing_toc[i]=xpt[i];
  1160.                         }
  1161.                         if(verbose) printf("  Xing VBR header found (info: %d frames, TOC=%s)\n",xing_frames,((xing_flags&XING_FLAG_TOC)?"yes":"no"));
  1162.  
  1163.                     }
  1164.                 }
  1165.  
  1166.                 freq=mpg_freq[curr_load->freq];
  1167.                 mono=(curr_load->mode==MPG_MD_MONO) ? 1 : 0;
  1168.                 layer=curr_load->layer;
  1169.                 setpos_framesize=curr_load->framesize;
  1170.  
  1171.                 duration=(double)bytes_total/((double)freq/1152.0)/(double)curr_load->framesize;
  1172.                 r1=mpg_bitrate[layer-1][curr_load->br_ind];
  1173.                 if(xingvbr && xing_frames)
  1174.                 {
  1175.                     duration=(double)xing_frames*1152.0/(double)freq;
  1176.                     r1=(LONG)((double)bytes_total/duration/125.0);
  1177.                 }
  1178.                 sprintf(rexxfiletypebuf,
  1179.                         "layer %s  %s%03d kbps  %ld Hz  %s",
  1180.                         mpg_layername[layer-1],
  1181.                         (xingvbr && xing_frames) ? "VBR avg. " : "",
  1182.                         r1,
  1183.                         freq,
  1184.                         mpg_modename[curr_load->mode] );
  1185.                 printf("  type: %s\n",rexxfiletypebuf);
  1186.                 rexxduration=(ULONG)(duration+0.5);
  1187.                 millisec=(ULONG)(1000.0*modf(duration,&duration2));
  1188.                 minutes=(ULONG)(duration2/60.0);
  1189.                 seconds=(ULONG)(duration2-minutes*60.0);
  1190.                 printf("  time: %02ld min %02ld.%03ld sec\n",minutes,seconds,millisec);
  1191.                 if(verbose) printf("  filesize / framesize: %ld / %ld bytes\n",bytes_total,curr_load->framesize);
  1192.                 if(outfile) printf("  output file: %s\n",outfilename);
  1193.  
  1194.                 if(showtag && havetag)
  1195.                 {
  1196.                     printf( "  TAG ID3v1\n      title: %s\n     artist: %s\n"
  1197.                             "      album: %s\n    comment: %s\n"
  1198.                             "       year: %s    genre: %d\n",
  1199.                             &ID3v1_buffer[00], /* title  */
  1200.                             &ID3v1_buffer[31], /* artist */
  1201.                             &ID3v1_buffer[62], /* album  */
  1202.                             &ID3v1_buffer[98], /* comment*/
  1203.                             &ID3v1_buffer[93], /* year   */
  1204.                             (int)ID3v1_buffer[141] ); /* genre  */
  1205.                 }
  1206.  
  1207.                 prevheader=currheader;
  1208.                 curr_load=curr_load->next;
  1209.  
  1210.                 rexxerror=10;  /* initDelfina failed */
  1211.                 if(InitDelfina())
  1212.                 {
  1213.                     rexxerror=0;    /* ok */
  1214.                     if(outfile) printf("  decoding...");
  1215.                     else        printf("  playing...");
  1216.                     fflush(stdout);
  1217.                     if(!outfile) taskpri=SetTaskPri(mytask,3);
  1218.                     GetSysTime(&time1);
  1219.                     if(pause>0) pause--;
  1220.                     /*
  1221.                     **
  1222.                     ** frames loop **
  1223.                     **
  1224.                     */
  1225.                     while(!ende)
  1226.                     {
  1227.                         if(rexxmode) handleRexx();
  1228.                         sigs=CheckSignal(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F);
  1229.                         if(sigs&SIGBREAKF_CTRL_C)
  1230.                         {
  1231.                             printf(" break CTRL-C\n");
  1232.                             break;  /* exit frames loop */
  1233.                         }
  1234.                         if(sigs&SIGBREAKF_CTRL_D)
  1235.                         {
  1236.                             ende=2;
  1237.                             printf(" break CTRL-D\n");
  1238.                             break;  /* exit frames loop */
  1239.                         }
  1240.                         if(outfile)
  1241.                         {
  1242.                             if(trigger_irq) Delf_Run( prg_pcm->prog+PROG_PCM_INTERRUPT, 0, DRUNF_ASYNCH, 0, 0, 0, 0 );
  1243.                         }
  1244.                         else
  1245.                         {
  1246.                             if(sigs&SIGBREAKF_CTRL_E)
  1247.                             {
  1248.                                 if(pause)
  1249.                                 {
  1250.                                     pause=0;
  1251.                                     rexxstatus=1;   /* play */
  1252.                                     printf("\n  playing...");
  1253.                                 }
  1254.                                 else
  1255.                                 {
  1256.                                     pause=1;
  1257.                                     rexxstatus=2;   /* pause */
  1258.                                     printf(" pause");
  1259.                                 }
  1260.                                 fflush(stdout);
  1261.                             }
  1262.                             if(sigs&SIGBREAKF_CTRL_F)
  1263.                             {
  1264.                                 pause++;
  1265.                                 i=ffskip;
  1266.                                 while((buffers_filled>0) && (i>0))
  1267.                                 {
  1268.                                     curr_play=curr_play->next;
  1269.                                     buffers_filled--; i--;
  1270.                                     frames_played++;
  1271.                                     if((layer==3) && (buffers_filled>0))
  1272.                                         BitReservoir(curr_play);
  1273.                                 }
  1274.                                 pause--;
  1275.                             }
  1276.                         }
  1277.                         if( (buffers_filled<framebuf) &&
  1278.                             (bytes_loaded<bytes_total) )
  1279.                         {
  1280.                             if(ReadAsync(file,&currheader,4)==4)
  1281.                                 if(ReadFrame(curr_load))
  1282.                                 {
  1283.                                     prevheader=currheader;
  1284.                                     curr_load=curr_load->next;
  1285.                                 }
  1286.                                 else bytes_loaded=bytes_total; /* force EOF */
  1287.                             else bytes_loaded=bytes_total;
  1288.                         }
  1289.                         else if(write_buffers_filled>0)
  1290.                         {
  1291.                             if(forcemono?1:mono) i=1152*2;
  1292.                             else i=1152*2*2;
  1293.                             if(WriteAsync(outfile,curr_write->data,i)!=i)
  1294.                             {
  1295.                                 printf("**error writing to output file.\n");
  1296.                                 rc=20;
  1297.                                 break; /* exit frames loop */
  1298.                             }
  1299.                             curr_write=curr_write->next;
  1300.                             write_buffers_filled--;
  1301.                         }
  1302.                         else
  1303.                         {
  1304.                             if( (bytes_loaded>=bytes_total) &&
  1305.                                 (buffers_filled==0) &&
  1306.                                 (frames_loaded==frames_played) )
  1307.                             {
  1308.                                 printf(" done.\n");
  1309.                                 break;  /* exit frames loop */
  1310.                             }
  1311.                             if(!notimer)    /* print timer */
  1312.                             {
  1313.                                 curr_print_pos=(frames_played*1152)/freq;
  1314.                                 if(prev_print_pos!=curr_print_pos)
  1315.                                 {
  1316.                                     rexxposition=curr_print_pos;
  1317.                                     prev_print_pos=curr_print_pos;
  1318.                                     if(outfile) printf("\r  decoding... (%02d:%02d)", curr_print_pos/60, curr_print_pos%60);
  1319.                                     else        printf("\r  playing... (%02d:%02d)", curr_print_pos/60, curr_print_pos%60);
  1320.                                     fflush(stdout);
  1321.                                 }
  1322.                             }
  1323.                             Delay(1);
  1324.                         }
  1325.                     }
  1326.                     pause++; /* mute output */
  1327.                     GetSysTime(&time2);
  1328.                     if(!outfile) SetTaskPri(mytask,taskpri);
  1329.                     SubTime(&time2,&time1);
  1330.                     millisec=(ULONG)((double)time2.tv_micro/1000.0);
  1331.                     minutes=(ULONG)((double)time2.tv_secs/60.0);
  1332.                     seconds=(ULONG)((double)time2.tv_secs-minutes*60.0);
  1333.                     duration2=(double)time2.tv_secs+(double)time2.tv_micro/1000000.0;
  1334.                     if(verbose)
  1335.                     {
  1336.                         if(buffers_missed>5) /* prevent "unnecessary" warnings */
  1337.                             printf("**note: detected NO_INPUT_DATA %d times\n",buffers_missed);
  1338.                         if(decoder_busy>0)
  1339.                             printf("**note: detected DECODER_BUSY %d times (%d%%)\n",decoder_busy,decoder_busy*100/frames_played);
  1340.                         if(maindata_err>0)
  1341.                             printf("**note: detected MP3_MAINDATA_ERROR %d times\n",maindata_err);
  1342.                         printf("  frames played / loaded: %ld / %ld\n",frames_played,frames_loaded);
  1343.                         printf("  elapsed time: %02ld min %02ld.%03ld sec\n",minutes, seconds, millisec);
  1344.                     }
  1345.                     if(outfile)
  1346.                     {
  1347.                         if(!verbose) printf("  elapsed time: %02ld min %02ld.%03ld sec\n",minutes, seconds, millisec);
  1348.                         ende=2;
  1349.                     }
  1350.                 }
  1351.                 CleanupDelfina();
  1352.             }
  1353.             CloseAsync(file);
  1354.         }
  1355.         else printf("**unable to open file\n");
  1356.     } while(!ende);
  1357.  
  1358.  
  1359.     if(playlist_in_use)
  1360.     {
  1361.         APTR p;
  1362.         while((p=RemHead((struct List*)&playlist))) FreeMem(p,sizeof(struct playnode));
  1363.         if(playlist_currdir)
  1364.         {
  1365.             if(lock_olddir) { CurrentDir(lock_olddir); lock_olddir=NULL; }
  1366.             if(lock_newdir) { UnLock(lock_newdir); lock_newdir=NULL; }
  1367.             playlist_currdir=0;
  1368.         }
  1369.         playlist_in_use=0;
  1370.     }
  1371.     if(rtfilelist)
  1372.     {
  1373.         if(lock_olddir) { CurrentDir(lock_olddir); lock_olddir=NULL; }
  1374.         if(lock_newdir) { UnLock(lock_newdir); lock_newdir=NULL; }
  1375.         rtFreeFileList(rtfilelist); rtfilelist=NULL;
  1376.         if(ende<2) goto next_filereq;
  1377.     }
  1378.     if(rexxmode && (ende<2)) goto next_rexxloop;
  1379.  
  1380. exit_clean:
  1381.     cleanupRexx();
  1382.     if(outfile) CloseAsync(outfile);
  1383.     if(rdargs) FreeArgs(rdargs);
  1384.     if(framebuf0) FreeMem((APTR)framebuf0,framebuf0size);
  1385.     if(savebuf0) FreeMem((APTR)savebuf0,DEFAULT_OUTFILE_FRAMEBUF*(LONG)sizeof(struct savebuf));
  1386.     if(fib) FreeDosObject(DOS_FIB,fib);
  1387.     if(rtfilereq) rtFreeRequest(rtfilereq);
  1388.     if(ReqToolsBase) CloseLibrary((struct Library*)ReqToolsBase);
  1389.     if(AsyncIOBase) CloseLibrary(AsyncIOBase);
  1390.     if(DelfinaBase) CloseLibrary(DelfinaBase);
  1391.     return(rc);
  1392. }
  1393.